package com.buzz.middleware.dynamic.thread.pool.sdk.config;

import com.buzz.middleware.dynamic.thread.pool.sdk.domain.DynamicThreadPoolService;
import com.buzz.middleware.dynamic.thread.pool.sdk.domain.IDynamicThreadPoolService;
import com.buzz.middleware.dynamic.thread.pool.sdk.domain.model.ThreadPoolConfigEntity;
import com.buzz.middleware.dynamic.thread.pool.sdk.domain.valobj.RegistryEnumVO;
import com.buzz.middleware.dynamic.thread.pool.sdk.registry.IRegistry;
import com.buzz.middleware.dynamic.thread.pool.sdk.registry.redis.RedisRegistry;
import com.buzz.middleware.dynamic.thread.pool.sdk.trigger.job.ThreadPoolDataReportJob;
import com.buzz.middleware.dynamic.thread.pool.sdk.trigger.listener.ThreadPoolConfigAdjustListener;
import org.redisson.Redisson;
import org.redisson.api.RTopic;
import org.redisson.api.RedissonClient;
import org.redisson.codec.Kryo5Codec;
import org.redisson.config.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;

import java.util.Map;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @Author: LiBaoxuan
 * @CreateTime: 2025-01-04  18:57
 * @Description: TODO
 */
@Configuration
@EnableConfigurationProperties(DynamicThreadPoolAutoProperties.class)
@EnableScheduling
public class DynamicThreadPoolAutoConfig {

    Logger logger = LoggerFactory.getLogger(DynamicThreadPoolAutoConfig.class);

    private String applicationName;

    @Bean("dynamicThreadPoolRedissonClient")
    public RedissonClient redissonClient(DynamicThreadPoolAutoProperties properties) {
        Config config = new Config();
        config.setCodec(new Kryo5Codec());

        config.useSingleServer()
                .setAddress("redis://" + properties.getHost() + ":" + properties.getPort())
                .setPassword(properties.getPassword())
                .setConnectionPoolSize(properties.getPoolSize())
                .setConnectionMinimumIdleSize(properties.getMinIdleSize())
                .setIdleConnectionTimeout(properties.getIdleTimeout())
                .setConnectTimeout(properties.getConnectTimeout())
                .setRetryAttempts(properties.getRetryAttempts())
                .setRetryInterval(properties.getRetryInterval())
                .setPingConnectionInterval(properties.getPingInterval())
                .setKeepAlive(properties.isKeepAlive())
        ;

        RedissonClient redissonClient = Redisson.create(config);

        logger.info("动态线程池，注册器（redis）链接初始化完成。{} {} {}", properties.getHost(), properties.getPoolSize(), !redissonClient.isShutdown());

        return redissonClient;
    }

    @Bean
    public IRegistry redisRegistry(RedissonClient dynamicThreadPoolRedissonClient) {
        return new RedisRegistry(dynamicThreadPoolRedissonClient);
    }


    @Bean("dynamicThreadPoolService")
    public IDynamicThreadPoolService dynamicThreadPollService(ApplicationContext applicationContext, Map<String, ThreadPoolExecutor> threadPoolExecutorMap) {
        applicationName = applicationContext.getEnvironment().getProperty("spring.application.name");

        return new DynamicThreadPoolService(applicationName, threadPoolExecutorMap);
    }

    @Bean("threadPoolDataReportJob")
    public ThreadPoolDataReportJob threadPoolDataReportJob(IDynamicThreadPoolService dynamicThreadPoolService, IRegistry redisRegistry) {
        return new ThreadPoolDataReportJob(dynamicThreadPoolService, redisRegistry);
    }

    @Bean("dynamicThreadPoolRedisTopic")
    public RTopic dynamicThreadPoolRedisTopic(RedissonClient dynamicThreadPoolRedissonClient, IDynamicThreadPoolService dynamicThreadPollService, IRegistry redisRegistry) {
        RTopic topic = dynamicThreadPoolRedissonClient.getTopic(RegistryEnumVO.DYNAMIC_THREAD_POOL_REDIS_TOPIC.getKey() + "_" + applicationName);
        topic.addListener(ThreadPoolConfigEntity.class, new ThreadPoolConfigAdjustListener(dynamicThreadPollService, redisRegistry));
        return topic;
    }

}
